package com.kingyun.gpsinspection.purificationservice.services.activitiservice.base;

import com.cqhilink.api.common.utils.enums.RespCodeEnum;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kingyun.gpsinspection.purificationservice.common.bean.Page;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.activiti.BpmConfNodeMapper;
import com.kingyun.gpsinspection.purificationservice.facade.model.activiti.BpmConfNode;
import com.kingyun.gpsinspection.purificationservice.facade.service.activiti.base.WorkflowProcessDefinitionService;
import com.kingyun.gpsinspection.purificationservice.services.activitiservice.ext.util.ActivitiMakeDataUtil;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cmd.GetDeploymentProcessDefinitionCmd;
import org.activiti.engine.impl.cmd.GetDeploymentProcessDiagramCmd;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

/**
 * 流程定义与流程实例servieImpl
 * @author zjh
 * @since 20170525
 */
public  class BaseWorkflowProcessDefinitionServiceImpl implements WorkflowProcessDefinitionService {


    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected HistoryService historyService;

    @Autowired
    protected ManagementService managementService;

    @Autowired
    protected BpmConfNodeMapper bpmConfNodeMapper;



    /**
     * 通过流程定义Id得到流程定义对象
     *
     * @param processDefinitionId 流程定义Id
     * @return 流程定义对象
     */
    @Override
    public Map<String,Object> getProcessDefinitionByProcessDefinitionId(String processDefinitionId) {
        Map<String,Object> result= Maps.newHashMap();
        List<BpmConfNode> activitiList= Lists.newArrayList();
        List<BpmConfNode> bpmConfUsers = bpmConfNodeMapper.getBpmConfNodeByPid(processDefinitionId);
        int index=0;
        if(CollectionUtils.isEmpty(bpmConfUsers)){
            //在流程配置节点表中没有配置过
            GetDeploymentProcessDefinitionCmd getDeploymentProcessDefinitionCmd = new GetDeploymentProcessDefinitionCmd(processDefinitionId);
            ProcessDefinitionEntity processDefinitionEntity = managementService.executeCommand(getDeploymentProcessDefinitionCmd);
            List<ActivityImpl> activities = processDefinitionEntity.getActivities();
            for(ActivityImpl act :activities){
                BpmConfNode entity=new BpmConfNode();
                entity.setNodeId(act.getId());
                entity.setNodeName(act.getProperty("name").toString());
                entity.setNodeType(act.getProperty("type").toString());
                entity.setProcessDefinitionId(processDefinitionId);
                List<PvmTransition> outgoingTransitions = act.getOutgoingTransitions();
                for(PvmTransition transition:outgoingTransitions){
                    PvmActivity destination = transition.getDestination();
                    entity.getConditionAct().put(transition.getId(),destination.getId());
                }
                entity.setNodeSeq(index++);
                activitiList.add(entity);
            }
        }else{
            //在流程配置节点以及配置过
            for(BpmConfNode bpm:bpmConfUsers){
                bpm.setNodeSeq(index++);
            }
            activitiList=bpmConfUsers;
        }
        result.put("rows",activitiList);
        result.put("total",activitiList.size());
        return result;
    }

    /**
     * 得到流程图片
     *
     * @param processDefinitionId 流程定义ID
     * @return
     */
    @Override
    public byte[] getProcessDefinitionDiagram(String processDefinitionId) throws Exception {
        GetDeploymentProcessDiagramCmd processDiagramCmd = new GetDeploymentProcessDiagramCmd(processDefinitionId);
        InputStream inputStream = managementService.executeCommand(processDiagramCmd);
        byte[] bytes=new byte[inputStream.available()];
        inputStream.read(bytes);
        return bytes;
    }

    /**
     * 发布流程定义
     *
     * @param bytes
     * @return
     */
    @Override
    public Map<String, Object> deploy(byte[] bytes) {
        Map<String,Object> result=Maps.newHashMap();
        ZipInputStream zipInputStream=new ZipInputStream(new ByteArrayInputStream(bytes));
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().addZipInputStream(zipInputStream);
        Deployment deploy = deploymentBuilder.deploy();
        if(deploy!=null&& !Strings.isNullOrEmpty(deploy.getId())){
            result.put("state", RespCodeEnum.RESP_CODE_ENUM_true.code());
            result.put("msg","流程"+deploy.getName()+"发布成功");
        }else{
            result.put("state", RespCodeEnum.RESP_CODE_ENUM_false.code());
            result.put("msg","流程发布失败");
        }
        return result;
    }

    /**
     * 删除已经部署的流程定义
     *
     * @param deploymentId 流程定义部署ID
     * @param cascade             是否级联删除
     * @return
     */
    @Override
    public Map<String, Object> deleteDeployment(String deploymentId, boolean cascade) {
        Map<String,Object> result=Maps.newHashMap();
        repositoryService.deleteDeployment(deploymentId,cascade);
        result.put("state",RespCodeEnum.RESP_CODE_ENUM_true.code());
        result.put("msg","删除流程定义成功");
        return result;
    }

    /**
     * 得到所有的流程定义
     *
     * @param page 分页参数
     * @return
     */
    @Override
    public Page getProcessDefinitionByPage(Page page) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        if(page==null){
            throw new IllegalArgumentException("参数不正确");
        }
        if(page.getParams()!=null){
            //TODO拼装查询参数
        }
        List<ProcessDefinition> processDefinitions = processDefinitionQuery.active().listPage(page.getOffset(), page.getLimit());
        long processDefinitionCount = processDefinitionQuery.count();

        page.setRows(ActivitiMakeDataUtil.makeProcessDefinitionData(processDefinitions));
        page.setTotal(processDefinitionCount);
        return page;
    }




}
